package org.codehaus.activemq.capacity;

import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList;
import java.util.Iterator;

public class BasicCapacityMonitor
  implements CapacityMonitor
{
  private String name;
  private long valueLimit;
  private long currentValue = 0L;
  private int currentCapacity = 100;
  private int roundedCapacity = 100;
  private int roundingFactor = 10;
  private CopyOnWriteArrayList listeners = new CopyOnWriteArrayList();

  public BasicCapacityMonitor(String name, long valueLimit)
  {
    this.name = name;
    this.valueLimit = valueLimit;
  }

  public String getName()
  {
    return this.name;
  }

  public void setName(String newName)
  {
    this.name = newName;
  }

  public int getRoundingFactor()
  {
    return this.roundingFactor;
  }

  public void setRoundingFactor(int newRoundingFactor)
  {
    if ((newRoundingFactor < 1) || (newRoundingFactor > 100)) {
      throw new IllegalArgumentException("invalid roundingFactor: " + newRoundingFactor);
    }
    this.roundingFactor = newRoundingFactor;
  }

  public void addCapacityEventListener(CapacityMonitorEventListener l)
  {
    this.listeners.add(l);
  }

  public void removeCapacityEventListener(CapacityMonitorEventListener l)
  {
    this.listeners.remove(l);
  }

  public int getCurrentCapacity()
  {
    return this.currentCapacity;
  }

  public int getRoundedCapacity()
  {
    return this.roundedCapacity;
  }

  public long getCurrentValue()
  {
    return this.currentValue;
  }

  public void setCurrentValue(long newCurrentValue)
  {
    this.currentValue = newCurrentValue;
    int newCapacity = calculateCapacity();
    int newRoundedCapacity = newCapacity > 0 ? newCapacity / this.roundingFactor * this.roundingFactor : 0;
    updateCapacityChanged(newRoundedCapacity);
    this.currentCapacity = newCapacity;
    this.roundedCapacity = newRoundedCapacity;
  }

  public long getValueLimit()
  {
    return this.valueLimit;
  }

  public void setValueLimit(long newValueLimit)
  {
    this.valueLimit = newValueLimit;

    setCurrentValue(this.currentValue);
  }

  private void updateCapacityChanged(int newRoundedCapacity)
  {
    CapacityMonitorEvent event;
    Iterator i;
    if ((this.listeners.size() > 0) && (newRoundedCapacity != this.roundedCapacity)) {
      event = new CapacityMonitorEvent(this.name, newRoundedCapacity);
      for (i = this.listeners.iterator(); i.hasNext(); ) {
        CapacityMonitorEventListener listener = (CapacityMonitorEventListener)i.next();
        listener.capacityChanged(event);
      }
    }
  }

  private int calculateCapacity()
  {
    int result = 100;
    if (this.currentValue != 0L) {
      result = (int)(100L - this.currentValue * 100L / this.valueLimit);
    }
    return result;
  }
}